home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 21 / CU Amiga Magazine's Super CD-ROM 21 (1998)(EMAP Images)(GB)[!][issue 1998-04].iso / CUCD / Programming / Python-1.4 / Python1.4_Source / Modules / doslibmodule.c < prev    next >
C/C++ Source or Header  |  1996-12-31  |  16KB  |  693 lines

  1.  
  2. /********************************************************************
  3.  
  4.     Lowlevel Amiga dos.library module.
  5.  
  6. -----------------------------------------------
  7.     ©1996,1997 by Irmen de Jong.
  8.  
  9.     History:
  10.  
  11.      9-jun-96   Created.
  12.     13-jun-96   Added WaitSignal().
  13.     17-nov-96   Fixed empty template handling.
  14.     31-dec-96   Changed CheckSignal to look like WaitSignal.
  15.  
  16. Module members:
  17.  
  18.     error       -- Exeption string object.  ('doslib.error')
  19.     ReadArgs    -- dos.library/ReadArgs function.
  20.                    result=doslib.ReadArgs(template,args,types)
  21.  
  22.     WaitSignal  -- generic Wait() function, like select. Waits for certain
  23.                    signals to occur.
  24.                    (sigs,objlist) = WaitSignal(args)
  25.                    args = integer, object, or list of ints/objects.
  26.                    integers are sigmask values. Objects must have 'signal'
  27.                    attribute to get this value.
  28.  
  29.     CheckSignal -- Like Wait() but DOES NOT WAIT FOR THE SIGNALS:
  30.                    merely checks if certain signals are set.
  31.  
  32.     CompareDates, DateStamp, DateToStr, StrToDate, Fault,
  33.     IoErr, SetIoErr, IsFileSystem, Relabel, SetProtection,
  34.     SetComment, Examine: just like the original dos.library calls.
  35.  
  36.     DS2time     -- convert DateStamp tuple to time() value (see time module)
  37.     time2DS     -- convert time() value to DateStamp tuple (see time module)
  38.  
  39.  
  40. **************************************************************************/
  41.  
  42. #include <stdlib.h>
  43. #include <exec/types.h>
  44. #include <exec/memory.h>
  45. #include <dos/dos.h>
  46. #include <dos/datetime.h>
  47. #include <dos/rdargs.h>
  48. #include <proto/dos.h>
  49. #include <proto/exec.h>
  50. #include "allobjects.h"
  51. #include "modsupport.h"
  52.  
  53.  
  54. static PyObject *error;    // Exception
  55.  
  56.  
  57. /* Convenience; sets error with IoError() string, return NULL */
  58. /* If ok, return Py_NONE */
  59. static PyObject *check_ok(BOOL ok)
  60. {
  61.     char buf[100];
  62.     if(ok)
  63.     {
  64.         Py_INCREF(Py_None);
  65.         return Py_None;
  66.     }
  67.  
  68.     Fault(IoErr(),NULL,buf,100);
  69.     PyErr_SetString(error,buf);
  70.     return NULL;
  71. }
  72.  
  73.  
  74. /************** MODULE FUNCTIONS *******************/
  75.  
  76. static PyObject *
  77. Doslib_ReadArgs(PyObject *self, PyObject *arg)
  78. {
  79.     char *template;
  80.     char *args;
  81.     PyObject *types;        // the keywords & their types (tuple of tuples)
  82.  
  83.     PyObject *result=NULL;
  84.  
  85.     LONG *argarray;
  86.     int num_args;
  87.     BOOL free_args=FALSE;
  88.     
  89.     if (!PyArg_ParseTuple(arg, "ssO!", &template, &args,
  90.         &PyTuple_Type,&types))
  91.         return NULL;
  92.  
  93.     if(PyTuple_Size(types)>0 || strlen(template)>0)
  94.     {
  95.         /* check argument count */
  96.         char *t=template;
  97.         num_args=1;
  98.         while(*t)
  99.         {
  100.             if(*t++ == ',') num_args++;
  101.         }
  102.         if(num_args!=PyTuple_Size(types))
  103.         {
  104.             PyErr_SetString(ValueError,"types length does not match template");
  105.             return NULL;
  106.         }
  107.     }
  108.     else
  109.     {
  110.         /* template is empty string; no arguments expected */
  111.         if(strlen(stpblk(args))>0)
  112.         {
  113.             SetIoErr(ERROR_TOO_MANY_ARGS);
  114.             return check_ok(FALSE);
  115.         }
  116.         return PyDict_New();        // empty result dictionary
  117.     }
  118.  
  119.     if(argarray=calloc(sizeof(LONG),num_args))
  120.     {
  121.         struct RDArgs *rdargs;
  122.         int arglen=strlen(args);
  123.  
  124.         if((arglen==0) || (args[arglen-1]!='\n'))
  125.         {
  126.             char *t = malloc(arglen+2);
  127.             if(t)
  128.             {
  129.                 strcpy(t,args); t[arglen++]='\n'; t[arglen]=0;  // add \n !!!
  130.                 args=t; free_args=TRUE;
  131.             }
  132.             else
  133.             {
  134.                 free(argarray);
  135.                 return PyErr_NoMemory();
  136.             }
  137.         }
  138.  
  139.         if(rdargs = AllocDosObject(DOS_RDARGS, NULL))
  140.         {
  141.             rdargs->RDA_Flags = RDAF_NOPROMPT;
  142.             rdargs->RDA_Source.CS_Buffer = args;
  143.             rdargs->RDA_Source.CS_Length = arglen;
  144.             rdargs->RDA_Source.CS_CurChr = 0;
  145.             rdargs->RDA_DAList = NULL;
  146.             rdargs->RDA_Buffer = NULL;
  147.  
  148.             if( !ReadArgs(template, argarray, rdargs) )
  149.             {
  150.                 (void)check_ok(FALSE);
  151.             }
  152.             else
  153.             {
  154.                 if(result=PyDict_New())
  155.                 {
  156.                     /************
  157.                     Traverse the types tuple and for each argument,
  158.                     extract it's value. types consists of tuples (k,t) where:
  159.                     k=keyword;
  160.                     t=the keyword's type:
  161.                         'X'     - string
  162.                         'S','T' - bool (integer)   !!! T not yet supported 
  163.                         'N'     - integer
  164.                         'A'     - array of strings
  165.                         'I'     - array of ints
  166.                     ***********/
  167.  
  168.                     PyObject *tup, *val;
  169.                     BOOL result_ok=TRUE;
  170.                     int cnt=0;
  171.                     while (result_ok && (tup=PyTuple_GetItem(types, cnt)))
  172.                     {
  173.                         PyObject *keyword, *type;
  174.                         char *type_c;
  175.  
  176.                         if(PyTuple_Size(tup)!=2)
  177.                         {
  178.                             PyErr_SetString(ValueError,"types tuple invalid");
  179.                             result_ok=FALSE; break;
  180.                         }
  181.  
  182.                         keyword=PyTuple_GetItem(tup,0);
  183.                         type=PyTuple_GetItem(tup,1);
  184.  
  185.                         result_ok=FALSE;
  186.                         type_c=PyString_AsString(type);
  187.                         if(type_c==NULL)
  188.                         {
  189.                             result_ok=FALSE; break; /* no string!? */
  190.                         }
  191.  
  192.                         switch (type_c[0]) {
  193.                         case 'S':       // boolean switch
  194.                             if(val=PyInt_FromLong(argarray[cnt]))
  195.                             {
  196.                                 result_ok=(0==PyDict_SetItem(result,keyword,val));
  197.                                 Py_DECREF(val);
  198.                             }
  199.                             break;
  200.                         case 'N':       // number
  201.                             if(argarray[cnt])
  202.                             {
  203.                                 if(val=PyInt_FromLong(*(LONG*)argarray[cnt]))
  204.                                 {
  205.                                     result_ok=(0==PyDict_SetItem(result,keyword,val));
  206.                                     Py_DECREF(val);
  207.                                 }
  208.                             }
  209.                             else result_ok=(0==PyDict_SetItem(result,keyword,Py_None));
  210.                             break;
  211.                         case 'X':       // string
  212.                             if(argarray[cnt])
  213.                             {
  214.                                 if(val=PyString_FromString((STRPTR)argarray[cnt]))
  215.                                 {
  216.                                     result_ok=(0==PyDict_SetItem(result,keyword,val));
  217.                                     Py_DECREF(val);
  218.                                 }
  219.                             }
  220.                             else result_ok=(0==PyDict_SetItem(result,keyword,Py_None));
  221.                             break;
  222.                         case 'A':       // array of strings
  223.                         case 'I':       // array of numbers
  224.                             if(val=PyList_New(0))
  225.                             {
  226.                                 if(argarray[cnt])
  227.                                 {
  228.                                     if(type_c[0]=='A')
  229.                                     {
  230.                                         char **str = (char**)argarray[cnt];
  231.                                         PyObject *so;
  232.                                         /* build the string list */
  233.                                         while(*str)
  234.                                         {
  235.                                             if(so=PyString_FromString(*str))
  236.                                             {
  237.                                                 if(!(result_ok=(0==PyList_Append(val,so))))
  238.                                                     break;
  239.                                                 Py_DECREF(so);
  240.                                             }
  241.                                             else break;
  242.                                             str++;
  243.                                         }
  244.                                     }
  245.                                     else /* array of numbers */
  246.                                     {
  247.                                         int **ia = (int**)argarray[cnt];
  248.                                         PyObject *io;
  249.                                         /* build the integer list */
  250.                                         while(*ia)
  251.                                         {
  252.                                             if(io=PyInt_FromLong(**ia))
  253.                                             {
  254.                                                 if(!(result_ok=(0==PyList_Append(val,io))))
  255.                                                     break;
  256.                                                 Py_DECREF(io);
  257.                                             }
  258.                                             else break;
  259.                                             ia++;
  260.                                         }
  261.                                     }
  262.                                     result_ok=result_ok&&(0==PyDict_SetItem(result,keyword,val));
  263.                                 }
  264.                                 else
  265.                                 {
  266.                                     // insert the empty list.
  267.                                     result_ok=(0==PyDict_SetItem(result,keyword,val));
  268.                                 }
  269.                                 Py_DECREF(val);
  270.                             }
  271.                             break;
  272.                         default:
  273.                             PyErr_SetString(ValueError,"illegal arg type");
  274.                             break;
  275.                         }
  276.                         cnt++;
  277.                     }
  278.                     if(!result_ok)
  279.                     {
  280.                         Py_DECREF(result);
  281.                         result=0;
  282.                     }
  283.                 }
  284.             }
  285.  
  286.             FreeArgs(rdargs);
  287.             FreeDosObject( DOS_RDARGS, rdargs );
  288.         }
  289.         else (void)PyErr_NoMemory();
  290.  
  291.         if(free_args) free(args);
  292.         free(argarray);
  293.     }
  294.     else (void)PyErr_NoMemory();
  295.  
  296.     return (PyObject*)result;
  297. }
  298.  
  299.  
  300. static PyObject *
  301. CheckOrWaitSignal(PyObject *self, PyObject *arg, BOOL doWait)
  302. {
  303.     struct {
  304.         PyObject *ob;       // the object, NULL means: only sigmask value
  305.         ULONG sigmask;
  306.     } objs[32];
  307.     int i,listsize = 0;
  308.     PyObject *argo, *result;
  309.     ULONG signal;
  310.  
  311.     if(!PyArg_ParseTuple(arg,"O",&argo)) return NULL;
  312.  
  313.     if(PyInt_Check(argo))
  314.     {
  315.         /* 1 int arg */
  316.         signal=PyInt_AsLong(argo);
  317.         objs[0].ob=NULL;
  318.         objs[0].sigmask=signal;
  319.         listsize++;
  320.     }
  321.     else if(PyList_Check(argo))
  322.     {
  323.         /* 1 list arg */
  324.         int len=PyList_Size(argo);
  325.  
  326.         if(len==0 || len>32)
  327.         {
  328.             PyErr_SetString(ValueError,"list size must be 1..32");
  329.             return NULL;
  330.         }
  331.  
  332.         signal = 0;
  333.  
  334.         for(i=0;i<len;i++)
  335.         {
  336.             PyObject *attr;
  337.             PyObject *item = PyList_GetItem(argo,i);
  338.             ULONG s;
  339.  
  340.             if(PyInt_Check(item))
  341.             {
  342.                 s = PyInt_AsLong(item);
  343.                 objs[listsize].ob = NULL;
  344.                 objs[listsize++].sigmask=s;
  345.                 signal |= s;
  346.             }
  347.             else if(attr = PyObject_GetAttrString(item,"signal"))
  348.             {
  349.                 ULONG s = PyInt_AsLong(attr);
  350.  
  351.                 if((s==-1) && PyErr_Occurred())
  352.                 {
  353.                     Py_DECREF(attr);
  354.                     return NULL;
  355.                 }
  356.                 
  357.                 signal |= s;
  358.                 objs[listsize].ob=item;
  359.                 objs[listsize++].sigmask=s;
  360.             }
  361.             else return (PyObject*)PyErr_BadArgument();
  362.         }
  363.     }
  364.     else
  365.     {
  366.         /* other, try signal attribute */
  367.         PyObject *attr;
  368.         if(attr=PyObject_GetAttrString(argo,"signal"))
  369.         {
  370.             /* Found! */
  371.             signal = PyInt_AsLong(attr);
  372.  
  373.             if((signal==-1) && PyErr_Occurred())
  374.             {
  375.                 Py_DECREF(attr);
  376.                 return NULL;
  377.             }
  378.  
  379.             objs[0].ob = attr;
  380.             objs[0].sigmask = signal;
  381.             listsize++;
  382.         }
  383.         else return NULL;
  384.     }
  385.     
  386.     if(doWait)
  387.         signal = Wait(signal);
  388.     else
  389.         signal = CheckSignal(signal);
  390.  
  391.     if(result=PyList_New(0))
  392.     {
  393.         PyObject *tup;
  394.  
  395.         for(i=0;i<listsize;i++)
  396.         {
  397.             if(objs[i].ob && (signal&objs[i].sigmask))
  398.             {
  399.                 if(0!=PyList_Append(result,objs[i].ob))
  400.                 {
  401.                     Py_DECREF(result);
  402.                     return NULL;
  403.                 }
  404.             }
  405.         }
  406.  
  407.         tup=Py_BuildValue("(iO)",signal,result);
  408.         Py_DECREF(result);
  409.         return tup;
  410.     }
  411.     else return NULL;
  412. }
  413.  
  414. static PyObject *
  415. Doslib_WaitSignal(PyObject *self, PyObject *arg)
  416. {
  417.     return CheckOrWaitSignal(self,arg,TRUE);
  418. }
  419.  
  420. static PyObject *
  421. Doslib_CheckSignal(PyObject *self, PyObject *arg)
  422. {
  423.     return CheckOrWaitSignal(self,arg,FALSE);
  424. }
  425.  
  426.  
  427. static PyObject *
  428. Doslib_DateToStr(PyObject *self, PyObject *arg)
  429. {
  430.     // (datestamp[,format=FORMAT_DOS,flags=0]) -> string
  431.  
  432.     struct DateTime dt;
  433.     PyObject *ds_t;
  434.     int flags=0,format=FORMAT_DOS;
  435.     char day[32];
  436.     char date[32];
  437.     char time[32];
  438.  
  439.     if(!PyArg_ParseTuple(arg,"O!|ii",&PyTuple_Type,&ds_t,&format,&flags)) return NULL;
  440.  
  441.     if(!PyArg_ParseTuple(ds_t,"iii;invalid datestamp tuple",
  442.         &dt.dat_Stamp.ds_Days,&dt.dat_Stamp.ds_Minute,&dt.dat_Stamp.ds_Tick)) return NULL;
  443.  
  444.     dt.dat_StrDay=day;
  445.     dt.dat_StrDate=date;
  446.     dt.dat_StrTime=time;
  447.     dt.dat_Flags=flags;
  448.     dt.dat_Format=format;
  449.     DateToStr(&dt);
  450.     return Py_BuildValue("(sss)",dt.dat_StrDay,dt.dat_StrDate,dt.dat_StrTime);  
  451. }
  452.  
  453. static PyObject *
  454. Doslib_StrToDate(PyObject *self, PyObject *arg)
  455. {
  456.     // (datestring[,timestring,format=FORMAT_DOS,flags=0]) -> datestamp
  457.  
  458.     struct DateTime dt;
  459.     
  460.     char *date;
  461.     char *time=NULL;
  462.     int flags=0,format=FORMAT_DOS;
  463.  
  464.     if(!PyArg_ParseTuple(arg,"s|sii",&date,&time,&format,&flags)) return NULL;
  465.  
  466.     memset(&dt,0,sizeof(dt));
  467.     dt.dat_StrDate=date;
  468.     dt.dat_StrTime=time;
  469.     dt.dat_Flags=flags;
  470.     dt.dat_Format=format;
  471.     StrToDate(&dt);
  472.     return Py_BuildValue("(iii)",dt.dat_Stamp.ds_Days,dt.dat_Stamp.ds_Minute,dt.dat_Stamp.ds_Tick);
  473. }
  474.  
  475. static PyObject *
  476. Doslib_CompareDates(PyObject *self, PyObject *arg)      // (ds1, ds2) -> <0,0,>0
  477. {
  478.     PyObject *ds_t1, *ds_t2;
  479.     struct DateStamp ds1,ds2;
  480.  
  481.     if(!PyArg_ParseTuple(arg,"O!O!",
  482.         &PyTuple_Type,&ds_t1,&PyTuple_Type,&ds_t2)) return NULL;
  483.  
  484.     if(!PyArg_ParseTuple(ds_t1,"iii;invalid datestamp tuple",&ds1.ds_Days,&ds1.ds_Minute,&ds1.ds_Tick)) return NULL;
  485.     if(!PyArg_ParseTuple(ds_t2,"iii;invalid datestamp tuple",&ds2.ds_Days,&ds2.ds_Minute,&ds2.ds_Tick)) return NULL;
  486.  
  487.     return PyInt_FromLong(CompareDates(&ds1,&ds2)); 
  488. }
  489.  
  490. static PyObject *
  491. Doslib_DateStamp(PyObject *self, PyObject *arg)     // () -> datestamp
  492. {
  493.     struct DateStamp ds;
  494.     if(!PyArg_NoArgs(arg)) return NULL;
  495.     
  496.     DateStamp(&ds);
  497.     return Py_BuildValue("(iii)",ds.ds_Days,ds.ds_Minute,ds.ds_Tick);
  498. }
  499.  
  500. static PyObject *
  501. Doslib_Fault(PyObject *self, PyObject *arg)         // (errnum[, header]) -> string
  502. {
  503.     int errnum;
  504.     char *header=NULL;
  505.     char buf[100];
  506.  
  507.     if(!PyArg_ParseTuple(arg,"i|s",&errnum,&header)) return NULL;
  508.     Fault(errnum,header,buf,100);
  509.     return PyString_FromString(buf);
  510. }
  511.  
  512. static PyObject *
  513. Doslib_IoErr(PyObject *self, PyObject *arg)         // () -> int
  514. {
  515.     if(!PyArg_NoArgs(arg)) return NULL;
  516.     return PyInt_FromLong(IoErr());
  517. }
  518.  
  519. static PyObject *
  520. Doslib_SetIoErr(PyObject *self, PyObject *arg)      // (int) -> int
  521. {
  522.     int errnum;
  523.  
  524.     if(!PyArg_ParseTuple(arg,"i",&errnum)) return NULL;
  525.     return PyInt_FromLong(SetIoErr(errnum));
  526. }
  527.  
  528. static PyObject *
  529. Doslib_IsFileSystem(PyObject *self, PyObject *arg)      // (string) -> bool
  530. {
  531.     char *name;
  532.  
  533.     if(!PyArg_ParseTuple(arg,"s",&name)) return NULL;
  534.     return PyInt_FromLong(IsFileSystem(name));
  535. }
  536.  
  537. static PyObject *
  538. Doslib_Relabel(PyObject *self, PyObject *arg)   // (oldvolname, newvolname)
  539. {
  540.     char *old, *new;
  541.  
  542.     if(!PyArg_ParseTuple(arg,"ss",&old,&new)) return NULL;
  543.     if(old[strlen(old)-1]!=':')
  544.     {
  545.         PyErr_SetString(ValueError,"volume name must end with :");
  546.         return NULL;
  547.     }
  548.     if(new[strlen(new)-1]==':')
  549.     {
  550.         PyErr_SetString(ValueError,"new name must not end with :");
  551.         return NULL;
  552.     }
  553.     return check_ok(Relabel(old,new));
  554. }
  555.  
  556. static PyObject *
  557. Doslib_SetProtection(PyObject *self, PyObject *arg) // (file,protbits) -> bool
  558. {
  559.     char *name;
  560.     int pb;
  561.  
  562.     if(!PyArg_ParseTuple(arg,"si",&name,&pb)) return NULL;
  563.  
  564.     return check_ok(SetProtection(name,pb));
  565. }
  566.  
  567. static PyObject *
  568. Doslib_Examine(PyObject *self, PyObject *arg)       // (filename) -> fib structure
  569. {
  570.     char *name;
  571.     BPTR lock;
  572.     struct FileInfoBlock __aligned fib;
  573.  
  574.     if(!PyArg_ParseTuple(arg,"s",&name)) return NULL;
  575.     if(lock=Lock(name,ACCESS_READ))
  576.     {
  577.         if(Examine(lock,&fib))
  578.         {
  579.             UnLock(lock);
  580.             return Py_BuildValue("(siiiii(iii)sii)",
  581.                 fib.fib_FileName,
  582.                 fib.fib_Size,
  583.                 fib.fib_DirEntryType,
  584.                 fib.fib_Protection,
  585.                 fib.fib_DiskKey,
  586.                 fib.fib_NumBlocks,
  587.                 fib.fib_Date.ds_Days, fib.fib_Date.ds_Minute, fib.fib_Date.ds_Tick,
  588.                 fib.fib_Comment,
  589.                 fib.fib_OwnerUID,
  590.                 fib.fib_OwnerGID);
  591. /******************
  592.             return Py_BuildValue("(iisiiii(iii)sii)",
  593.                 fib.fib_DiskKey,
  594.                 fib.fib_DirEntryType,
  595.                 fib.fib_FileName,
  596.                 fib.fib_Protection,
  597.                 fib.fib_EntryType,
  598.                 fib.fib_Size,
  599.                 fib.fib_NumBlocks,
  600.                 fib.fib_Date.ds_Days, fib.fib_Date.ds_Minute, fib.fib_Date.ds_Tick,
  601.                 fib.fib_Comment,
  602.                 fib.fib_OwnerUID,
  603.                 fib.fib_OwnerGID);
  604. ******************/
  605.         }
  606.         UnLock(lock);
  607.     }
  608.     return check_ok(FALSE);
  609. }
  610.  
  611. static PyObject *
  612. Doslib_SetComment(PyObject *self, PyObject *args)
  613. {
  614.     char *path, *note;
  615.  
  616.     if (!PyArg_ParseTuple(args, "ss", &path,¬e)) return NULL;
  617.     return check_ok(SetComment(path,note));
  618. }
  619.  
  620.  
  621. /* the offset between DateStamp() and time() epoch: */
  622. #define TIME_OFFSET 252457200.0
  623.  
  624. static PyObject *
  625. Doslib_DS2time(PyObject *self, PyObject *args)
  626. {
  627.     struct DateStamp ds;
  628.  
  629.     if(!PyArg_ParseTuple(args,"(iii)",&ds.ds_Days,&ds.ds_Minute,&ds.ds_Tick)) return NULL;
  630.  
  631.     return PyFloat_FromDouble(
  632.         86400.0*ds.ds_Days + 60.0*ds.ds_Minute + ((double)ds.ds_Tick/50.0) + TIME_OFFSET
  633.     );
  634. }
  635.  
  636. static PyObject *
  637. Doslib_time2DS(PyObject *self, PyObject *args)
  638. {
  639.     double t;
  640.     int days,minutes,ticks;
  641.  
  642.     if(!PyArg_ParseTuple(args,"d",&t)) return NULL;
  643.  
  644.     t -= TIME_OFFSET;
  645.     days =  t / 86400.0;
  646.     t -= days*86400.0;
  647.     minutes = t / 60.0;
  648.     t -= minutes*60.0;
  649.     ticks = t*50.0;
  650.  
  651.     return Py_BuildValue("(iii)",days,minutes,ticks);
  652. }
  653.  
  654.  
  655.  
  656. /*** FUNCTIONS FROM THE MODULE ***/
  657.  
  658. static struct methodlist Doslib_global_methods[] = {
  659.     {"ReadArgs", Doslib_ReadArgs, 1},
  660.     {"WaitSignal", Doslib_WaitSignal, 1},
  661.     {"CheckSignal", Doslib_CheckSignal, 1},
  662.     {"CompareDates", Doslib_CompareDates, 1},
  663.     {"DateStamp", Doslib_DateStamp, 0},
  664.     {"DateToStr", Doslib_DateToStr, 1},
  665.     {"StrToDate", Doslib_StrToDate, 1},
  666.     {"Fault", Doslib_Fault, 1},
  667.     {"IoErr", Doslib_IoErr, 0},
  668.     {"SetIoErr", Doslib_SetIoErr, 1},
  669.     {"IsFileSystem", Doslib_IsFileSystem, 1},
  670.     {"Relabel", Doslib_Relabel, 1},
  671.     {"SetProtection", Doslib_SetProtection, 1},
  672.     {"SetComment", Doslib_SetComment, 1},
  673.     {"Examine", Doslib_Examine, 1},
  674.     {"DS2time", Doslib_DS2time, 1},
  675.     {"time2DS", Doslib_time2DS, 1},
  676.     {NULL,      NULL}       /* sentinel */
  677. };
  678. ///
  679.  
  680. void
  681. initdoslib Py_PROTO((void))
  682. {
  683.     PyObject *m, *d;
  684.  
  685.     m = Py_InitModule("doslib", Doslib_global_methods);
  686.     d = PyModule_GetDict(m);
  687.  
  688.     /* Initialize error exception */
  689.     error = PyString_FromString("doslib.error");
  690.     if (error == NULL || PyDict_SetItemString(d, "error", error) != 0)
  691.         Py_FatalError("can't define doslib.error");
  692. }
  693.